package com.hzhc.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzhc.entity.SysUser;
import com.hzhc.entity.SysUserSecurity;
import com.hzhc.entity.UserMember;
import com.hzhc.enumBean.ResultUtilCodeEnum;
import com.hzhc.mapper.SysUserMapper;
import com.hzhc.mapper.SysUserSecurityMapper;
import com.hzhc.mapper.UserMemberMapper;
import com.hzhc.service.SysUserSecurityService;
import com.hzhc.utils.ResultUtil;
import com.hzhc.vo.SysUserSecurityVo;
import lombok.RequiredArgsConstructor;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.time.LocalDateTime;
import java.util.List;
import java.util.regex.Pattern;

/**
 * <p>
 * 用户安全设置 服务实现类
 * </p>
 *
 * @author 1
 * @since 2024-06-24
 */
@Service
@RequiredArgsConstructor
public class SysUserSecurityServiceImpl extends ServiceImpl<SysUserSecurityMapper, SysUserSecurity> implements SysUserSecurityService {
    private final SysUserMapper sysUserMapper;
    private final UserMemberMapper userMemberMapper;

    @Override
    public List<SysUserSecurityVo> getAllList(Page<SysUserSecurity> page, SysUserSecurityVo vo) {
        IPage<SysUserSecurityVo> iPage = baseMapper.getAllList(page,vo);
        return iPage.getRecords();
    }

    @Override
    public ResultUtil<T> addPasswordSecurity(SysUserSecurityVo vo) {
        SysUserSecurity security = new SysUserSecurity();
        BeanUtils.copyProperties(vo,security);
        security.setCreateTime(LocalDateTime.now());
        String rules = security.getPasswordRules();

        String decodedRegex = null;
        try {
            decodedRegex = URLDecoder.decode(rules, "UTF-8");//转义解码
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        security.setPasswordRules(decodedRegex);
        String reg1 = "^(?=.*\\d)(?=.*[A-z])[\\da-zA-Z]{8,}$";//只能由字母、数字组成，>8位
        String reg2 = "^(?![a-zA-Z]+$)(?!\\d+$)(?![^\\da-zA-Z\\s]+$).{8,}$";//由字母、数字、特殊字符，任意2种组成，>8位
        String reg3 = "^(?=.*\\d)(?=.*[a-zA-Z])(?=.*[^\\da-zA-Z\\s]).{8,}$";//至少包含字母、数字、特殊字符，>8位
        if ("1".equals(vo.getPasswordStrength())){
            security.setPasswordRulesJava(reg1);
            security.setRuleDescription("弱密码：包含两类字符,且组合为(数字+小写字母)或(数字+大写字母),且长度大于等于8位。");
        }else if ("2".equals(vo.getPasswordStrength())){
            security.setPasswordRulesJava(reg2);
            security.setRuleDescription("中密码：包含两类字符,且组合不能为(数字+小写字母)和(数字+大写字母),且长度大于等于8位。");
        }else if ("3".equals(vo.getPasswordStrength())){
            security.setPasswordRulesJava(reg3);
            security.setRuleDescription("强密码：包含三类字符以上,且长度大于等于8位。");
        }
        boolean b = save(security);
        if (b){
            return ResultUtil.ok();
        }
        return ResultUtil.fail();
    }

    @Override
    public ResultUtil<T> updatePasswordSecurity(SysUserSecurityVo vo) {
        SysUserSecurity security = new SysUserSecurity();
        BeanUtils.copyProperties(vo,security);
        security.setUpdateTime(LocalDateTime.now());
        String rules = security.getPasswordRules();

        String decodedRegex = null;
        try {
            decodedRegex = URLDecoder.decode(rules, "UTF-8");//转义解码
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        security.setPasswordRules(decodedRegex);

        String reg1 = "^(?=.*\\d)(?=.*[A-z])[\\da-zA-Z]{8,}$";//只能由字母、数字组成，>8位
        String reg2 = "^(?![a-zA-Z]+$)(?!\\d+$)(?![^\\da-zA-Z\\s]+$).{8,}$";//由字母、数字、特殊字符，任意2种组成，>8位
        String reg3 = "^(?=.*\\d)(?=.*[a-zA-Z])(?=.*[^\\da-zA-Z\\s]).{8,}$";//至少包含字母、数字、特殊字符，>8位
        if ("1".equals(vo.getPasswordStrength())){
            security.setPasswordRulesJava(reg1);
            security.setRuleDescription("弱密码：包含两类字符,且组合为(数字+小写字母)或(数字+大写字母),且长度大于等于8位。");
        }else if ("2".equals(vo.getPasswordStrength())){
            security.setPasswordRulesJava(reg2);
            security.setRuleDescription("中密码：包含两类字符,且组合不能为(数字+小写字母)和(数字+大写字母),且长度大于等于8位。");
        }else if ("3".equals(vo.getPasswordStrength())){
            security.setPasswordRulesJava(reg3);
            security.setRuleDescription("强密码：包含三类字符以上,且长度大于等于8位。");
        }
        boolean b = updateById(security);
        if (b){
            return ResultUtil.ok();
        }
        return ResultUtil.fail();
    }

    @Override
    public ResultUtil<T> deletePasswordSecurity(Long id) {
        SysUserSecurity security = getById(id);
        security.setDisable(1);
        boolean b = updateById(security);
        if (b){
            return ResultUtil.ok();
        }
        return ResultUtil.fail();
    }

    @Override
    public ResultUtil<T> updateSecurityStatus(SysUserSecurityVo vo) {
        //先所有置为 禁用
        LambdaUpdateWrapper<SysUserSecurity> wrapper = new LambdaUpdateWrapper<>();
        wrapper.set(SysUserSecurity::getStatus,false);
        boolean b = update(wrapper);
        SysUserSecurity security = getById(vo.getId());
        if (vo.getStatus()){//启用
            security.setStatus(true);
            baseMapper.updateById(security);
        }
        if (b){
            return ResultUtil.ok();
        }
        return ResultUtil.fail();
    }

    @Override
    public ResultUtil<T> checkPasswordLevel(String password) {
        //后端获取启用的强度等级
        LambdaQueryWrapper<SysUserSecurity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysUserSecurity::getStatus,true);
        SysUserSecurity one = baseMapper.selectOne(wrapper);
        if (one==null){//库中没有启用的密码强度 则不用校验
            return ResultUtil.ok();
        }
        //校验
        boolean b = Pattern.matches(one.getPasswordRulesJava(), password);
        if (!b){
            return ResultUtil.build(400,one.getRuleDescription());
        }
        return ResultUtil.ok();
    }

    @Override
    public ResultUtil<List<SysUserSecurity>> getStrengthLevel() {
        //前端获取启用的强度等级
        LambdaQueryWrapper<SysUserSecurity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysUserSecurity::getStatus,1);
        List<SysUserSecurity> list = baseMapper.selectList(wrapper);
        if (list.size()==0){//库中没有启用的密码强度  则不用校验
            return ResultUtil.ok();
        }
        return ResultUtil.build(list, ResultUtilCodeEnum.SUCCESS);
    }

    @Override
    public String checkLoginFailure(String loginname,String path,Integer flag) {
        List<SysUserSecurity> securities = baseMapper.selectList(new QueryWrapper<SysUserSecurity>().eq("status", 1).eq("disable",0));
        if(securities.size()>0){
            if("app".equals(path)){
                QueryWrapper<UserMember> queryWrapper=new QueryWrapper();
                queryWrapper.eq("username", loginname);
                if(flag!=null){
                    queryWrapper.eq("user_type",flag);
                }
                UserMember userMember = userMemberMapper.selectOne(queryWrapper);
                if(userMember!=null){
                    if(userMember.getLoginTime()!=null && userMember.getLoginTime().isBefore(LocalDateTime.now())){
                        userMember.setLoginNum(0);
                        userMember.setLoginTime(null);
                    }
                    userMember.setLoginNum(userMember.getLoginNum()+1);
                    if(userMember.getLoginNum()==securities.get(0).getPasswordErrorNum()){
                        userMember.setLoginTime(LocalDateTime.now().plusMinutes(Long.valueOf(securities.get(0).getPasswordLockTime())));
                    }
                    if(userMember.getLoginNum()>securities.get(0).getPasswordErrorNum()){
                        return "账号已锁!";
                    }
                    userMemberMapper.updateById(userMember);
                    if(userMember.getLoginNum()>=securities.get(0).getPasswordErrorNum()){
                        return "账号已锁定,请"+securities.get(0).getPasswordLockTime()+"分钟后再试!";
                    }else{
                        return "用户名或密码错误,剩余"+String.valueOf(securities.get(0).getPasswordErrorNum()- userMember.getLoginNum())+"次登录机会";
                    }
                }else{
                    return "用户名不存在!";
                }
            }else{
                SysUser sysUser = sysUserMapper.selectOne(new QueryWrapper<SysUser>().eq("loginname", loginname));
                if(sysUser!=null){
                    if(sysUser.getLoginTime()!=null && sysUser.getLoginTime().isBefore(LocalDateTime.now())){
                        sysUser.setLoginNum(0);
                        sysUser.setLoginTime(null);
                    }
                    sysUser.setLoginNum(sysUser.getLoginNum()+1);
                    if(sysUser.getLoginNum()==securities.get(0).getPasswordErrorNum()){
                        sysUser.setLoginTime(LocalDateTime.now().plusMinutes(Long.valueOf(securities.get(0).getPasswordLockTime())));
                    }
                    if(sysUser.getLoginNum()>securities.get(0).getPasswordErrorNum()){
                        return "账号已锁!";
                    }
                    sysUserMapper.updateById(sysUser);
                    if(sysUser.getLoginNum()>=securities.get(0).getPasswordErrorNum()){
                        return "账号已锁定,请"+securities.get(0).getPasswordLockTime()+"分钟后再试!";
                    }else{
                        return "用户名或密码错误,剩余"+String.valueOf(securities.get(0).getPasswordErrorNum()- sysUser.getLoginNum())+"次登录机会";
                    }
                }else{
                    return "用户名不存在!";
                }
            }
        }
        return "用户名或密码错误";
    }
}
